home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dev / devExabyteTape.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  13KB  |  418 lines

  1. /* 
  2.  * devExabyteTape.c --
  3.  *
  4.  *      Procedures that set up command blocks and process sense
  5.  *    data for Exabyte tape drives.
  6.  * Definitions for sense data format and status information returned
  7.  * from Exabyte tape drives.  Reference, the "EXB-8200 8mm Tape Drive
  8.  * User's Guide" by Perfect Byte, Inc. 7121 Cass St. Omaha, NE 68132
  9.  *
  10.  * Copyright 1989 Regents of the University of California
  11.  * Permission to use, copy, modify, and distribute this
  12.  * software and its documentation for any purpose and without
  13.  * fee is hereby granted, provided that the above copyright
  14.  * notice appear in all copies.  The University of California
  15.  * makes no representations about the suitability of this
  16.  * software for any purpose.  It is provided "as is" without
  17.  * express or implied warranty.
  18.  */
  19.  
  20. #ifndef lint
  21. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/devExabyteTape.c,v 9.8 91/12/11 17:58:40 jhh Exp $ SPRITE (Berkeley)";
  22. #endif not lint
  23.  
  24.  
  25. #include <sprite.h>
  26. #include <stdio.h>
  27. #include <dev.h>
  28. #include <sys/scsi.h>
  29. #include <scsiTape.h>
  30. #include <scsiDevice.h>
  31. #include <stdlib.h>
  32. #include <fs.h>
  33. #include <exabyteTape.h>
  34. #include <string.h>
  35. #include <dev/exabyte.h>
  36.  
  37. /*
  38.  * The Exabyte drives have 1K blocks.
  39.  */
  40. #define EXABYTE_BLOCK_SIZE    1024
  41.  
  42.  
  43. /*
  44.  * Definitions for the mode select command.  The MODE_SELECT data
  45.  * consists of a 4 byte header, zero or one 8 byte block descriptors,
  46.  * and finally from zero to 4 bytes of Vendor Unique Parameters.
  47.  * For simplicity we'll always send 1 block descriptor and 4 parameter bytes.
  48.  */
  49.  
  50. typedef struct ExabyteModeSelBlock {
  51.     unsigned char density;        /* Density code == 0.  Only one dens. */
  52.     unsigned char highCount;        /* == 0 */
  53.     unsigned char midCount;        /* == 0 */
  54.     unsigned char lowCount;        /* == 0 */
  55.     unsigned char pad1;            /* Reserved */
  56.     unsigned char highLength;        /* Length of the blocks on tape */
  57.     unsigned char midLength;        /*    0 means variable length */
  58.     unsigned char lowLength;        /*    Default is 1024 bytes */
  59. } ExabyteModeSelBlock;        /* 8 Bytes */
  60.  
  61.  
  62. typedef struct ExabyteModeSelParams {
  63.     ScsiTapeModeSelectHdr    header;
  64.     ExabyteModeSelBlock    block;
  65. #if BYTE_ORDER == BIG_ENDIAN
  66.     unsigned char cartidgeType    :1;    /* 1 == p5 European.
  67.                      * 0 == P6 Domestic */
  68.     unsigned char        :3;    /* Reserved */
  69.     unsigned char noBusyEnable    :1;    /* 0 == Report Busy Status (default)
  70.                      * 1 == No Busy Enable, cmd queued */
  71.     unsigned char evenByteDscnct :1;    /* 0 == Even or Odd byte disconnect
  72.                      * 1 == Even Byte disconnect */
  73.     unsigned char parityEnable    :1;    /* 0 == Parity disabled (default) */
  74.     unsigned char noAutoLoad    :1;    /* 0 == Auto load enabled (default) */
  75. #else /* BYTE_ORDER == LITTLE_ENDIAN */
  76.  
  77.     unsigned char noAutoLoad    :1;    /* 0 == Auto load enabled (default) */
  78.     unsigned char parityEnable    :1;    /* 0 == Parity disabled (default) */
  79.  
  80.     unsigned char evenByteDscnct :1;    /* 0 == Even or Odd byte disconnect
  81.                      * 1 == Even Byte disconnect */
  82.     unsigned char noBusyEnable    :1;    /* 0 == Report Busy Status (default)
  83.                      * 1 == No Busy Enable, cmd queued */
  84.  
  85.     unsigned char        :3;    /* Reserved */
  86.     unsigned char cartidgeType    :1;    /* 1 == p5 European.
  87.                      * 0 == P6 Domestic */
  88.  
  89. #endif /* BYTE_ORDER */
  90.     unsigned char pad1;            /* RESERVED */
  91.     /*
  92.      * The Motion threashold must exceed the Reconnect threshold.
  93.      * Values represent 1K byte increments.
  94.      * Motion - default 0xF0, valid range 0x01 -> 0xF7
  95.      * Reconnect - default 0x40, valid range 0x01 to 0xF7
  96.      * WRITE - lower motion threshold for faster transfer.
  97.      * READ - raise reconnect threshold for faster transfer.
  98.      *    Basically these control the amount of data kept in the buffer
  99.      *    and hence the latency.
  100.      */
  101.     unsigned char motion;        /* Defines how many Kbytes are buffered
  102.                      * before writing to the tape begins,
  103.                      * or when reconnecting on a read */
  104.     unsigned char reconnect;        /* Defines how many Kbytes are left
  105.                      * in the buffer when the drive
  106.                      * begins filling it again, either
  107.                      * by reading the tape or reconnecting
  108.                      * and getting more data from the 
  109.                      * SCSI bus. */
  110. } ModeSelParams;
  111.  
  112.  
  113. /*
  114.  * Parameter list header returned by mode sense.
  115.  */
  116.  
  117. typedef struct {
  118. #if BYTE_ORDER == BIG_ENDIAN
  119.     unsigned char modeDataLen;        /* Size of mode parameter data. */
  120.     unsigned char mediumType;        /* Type of medium. */
  121.     unsigned char writeProtect  :1;     /* Write protect. */
  122.     unsigned char bufferedMode  :3;       /* Buffered mode. */
  123.     unsigned char speed        :4;    /* Speed. */
  124.     unsigned char blockDescLen;        /* Block descriptor length. */
  125. #else
  126.     unsigned char modeDataLen;        /* Size of mode parameter data. */
  127.     unsigned char mediumType;        /* Type of medium. */
  128.     unsigned char speed        :4;    /* Speed. */
  129.     unsigned char bufferedMode  :3;       /* Buffered mode. */
  130.     unsigned char writeProtect  :1;     /* Write protect. */
  131.     unsigned char blockDescLen;        /* Block descriptor length. */
  132. #endif
  133. } ParamListHeader;
  134.  
  135. /*
  136.  * Block descriptor returned by mode sense.
  137.  */
  138.  
  139. typedef struct {
  140.     unsigned char    density;    /* Density code. */
  141.     unsigned char    num2;        /* MSB of number of blocks. */
  142.     unsigned char    num1;        /* ... */
  143.     unsigned char    num0;        /* LSB of number of blocks. */
  144.     unsigned char    pad0;        /* Reserved. */
  145.     unsigned char    len2;        /* MSB of block length. */
  146.     unsigned char    len1;        /* ... */
  147.     unsigned char    len0;        /* LSB of block length. */
  148. } BlockDesc;
  149.  
  150. /*
  151.  * Exabyte 8500 Inquiry data.
  152.  */
  153.  
  154. typedef struct {
  155.     ScsiInquiryData    stdData;
  156.     char        padding[52];
  157.     char        serial[10];
  158. } Exb8500Inquiry;
  159.  
  160. static ReturnStatus ExabyteError _ARGS_((ScsiDevice *devPtr,
  161.     ScsiCmd *scsiCmdPtr));
  162. ReturnStatus DevExabyteStatus _ARGS_((ScsiTape *tapePtr, 
  163.     Dev_TapeStatus *statusPtr, Boolean *readPositionPtr));
  164.  
  165.  
  166. /*
  167.  *----------------------------------------------------------------------
  168.  *
  169.  * DevExabyteAttach --
  170.  *
  171.  *    Initialize the DevSCSITape state for a Exabyte drive.
  172.  *
  173.  * Results:
  174.  *    None.
  175.  *
  176.  * Side effects:
  177.  *    Sets the type and call-back procedures.
  178.  *
  179.  *----------------------------------------------------------------------
  180.  */
  181. /*ARGSUSED*/
  182. ReturnStatus
  183. DevExabyteAttach(devicePtr, devPtr, tapePtr)
  184.     Fs_Device    *devicePtr;    /* Fs_Device being attached. */
  185.     ScsiDevice    *devPtr;    /* SCSI device handle for drive. */
  186.     ScsiTape    *tapePtr;    /* Tape drive state to be filled in. */
  187. {
  188.     ScsiInquiryData    *inquiryPtr;
  189.     /*
  190.      * First we must verify that the attached device is a Exabyte. We do
  191.      * that by examinging the Inquiry data in the ScsiDevice handle. The
  192.      * lack of Inquiry data would imply its not a Exabyte. 
  193.      */
  194.     inquiryPtr = (ScsiInquiryData *) (devPtr->inquiryDataPtr);
  195.     if ( (devPtr->inquiryLength < sizeof(ScsiInquiryData)) ||
  196.      (strncmp((char *) (inquiryPtr->vendorID), "EXABYTE ",8) != 0) ) {
  197.      return DEV_NO_DEVICE;
  198.     }
  199.     /*
  200.      * The exabyte has a different BLOCK and we liked to check the
  201.      * vendor unique bits on error.
  202.      */
  203.     tapePtr->blockSize = EXABYTE_BLOCK_SIZE;
  204.     devPtr->errorProc = ExabyteError;
  205.     if (!(strncmp((char *) inquiryPtr->productID, "EXB-8200",8))) {
  206.     tapePtr->name = "Exabyte 8200";
  207.     tapePtr->type = DEV_TAPE_EXB8200;
  208.     } else if (!(strncmp((char *) inquiryPtr->productID, "EXB-8500",8))) {
  209.     tapePtr->name = "Exabyte 8500";
  210.     tapePtr->type = DEV_TAPE_EXB8500;
  211.     } else {
  212.     tapePtr->name = "Exabyte UNKNOWN";
  213.     }
  214.     tapePtr->statusProc = DevExabyteStatus;
  215.     return SUCCESS;
  216. }
  217.  
  218. /*
  219.  *----------------------------------------------------------------------
  220.  *
  221.  * ExabyteError --
  222.  *
  223.  *    Handle error conditions from a Exabyte based tape drive.
  224.  *
  225.  * Results:
  226.  *    An error code.
  227.  *
  228.  * Side effects:
  229.  *    None.
  230.  *
  231.  *----------------------------------------------------------------------
  232.  */
  233. static ReturnStatus
  234. ExabyteError(devPtr, scsiCmdPtr)
  235.     ScsiDevice     *devPtr;    /* SCSI device that's complaining. */
  236.     ScsiCmd    *scsiCmdPtr;    /* SCSI command that had the problem. */
  237. {
  238.     ReturnStatus status;
  239.     register volatile Exb8200Sense *exabyteSensePtr =
  240.         (volatile Exb8200Sense *) scsiCmdPtr->senseBuffer;
  241.     Exb8500Sense *newSensePtr;
  242.  
  243.     status = DevSCSITapeError(devPtr, scsiCmdPtr);
  244.     if (status == SUCCESS) {
  245.     return status;
  246.     }
  247.     if (exabyteSensePtr->extSense.badBlockLen) {
  248.     printf("Exabyte Block Length Mismatch\n");
  249.     status = DEV_HARD_ERROR;
  250.     }
  251.     if (exabyteSensePtr->TMD) {
  252.         printf("Warning: Exabyte Tape Mark Detect error\n");
  253.         status = DEV_HARD_ERROR;
  254.     } 
  255.     if (exabyteSensePtr->XFR) {
  256.         printf("Warning: Exabyte Transfer abort error\n");
  257.         status = DEV_HARD_ERROR;
  258.     }
  259.     if (exabyteSensePtr->PF) {
  260.     /* Media changed or after power up */
  261.     }
  262.     if (exabyteSensePtr->BPE) {
  263.     printf("Warning: Exabyte SCSI Bus Parity error\n");
  264.     }
  265.     if (exabyteSensePtr->FPE) {
  266.     printf("Warning: Exabyte Formatter Parity error\n");
  267.     }
  268.     if (exabyteSensePtr->ME) {
  269.     /* Media Error already reported via sense key */
  270.     }
  271.     if (exabyteSensePtr->ECO) {
  272.     printf("Warning: Exabyte error counter overflow\n");
  273.     }
  274.     if (exabyteSensePtr->TME) {
  275.     printf("Warning: Exabyte Tape Motion error\n");
  276.     }
  277.     if (exabyteSensePtr->TNP) {
  278.     printf("Warning: Exabyte tape not present\n");
  279.     }
  280.     if (exabyteSensePtr->BOT) {
  281.     /* At the beginning of tape */
  282.     }
  283.     if (exabyteSensePtr->FMKE) {
  284.     printf("Exabyte File Mark Error\n");
  285.     }
  286.     if (exabyteSensePtr->URE) {
  287.     printf("Warning: Exabyte Data Flow Underrun\n");
  288.     }
  289.     if (exabyteSensePtr->WE1) {
  290.     printf("Warning: Exabyte maximum write retries attempted\n");
  291.     }
  292.     if (exabyteSensePtr->SSE) {
  293.     printf("Warning: Exabyte Servo System error, catastrophic failure!\n");
  294.     }
  295.     if (exabyteSensePtr->FE) {
  296.     printf("Warning: Exabyte Formatter error, catastrophic failure!\n");
  297.     }
  298.     printf("Additional Sense Code: 0x%x\n", exabyteSensePtr->senseCode);
  299.     printf("Additional Sense Code Qualifier: 0x%x\n", 
  300.     exabyteSensePtr->senseCodeQualifier);
  301.     if (scsiCmdPtr->senseLen == sizeof(Exb8500Sense)) {
  302.     newSensePtr = (Exb8500Sense *) exabyteSensePtr;
  303.     printf("EXB8500 Fault Symptom Code = 0x%x\n", newSensePtr->faultCode);
  304.     }
  305.     return(status);
  306. }
  307.  
  308. /*
  309.  *----------------------------------------------------------------------
  310.  *
  311.  * DevExabyteStatus --
  312.  *
  313.  *    Fill in some of the fields in the status structure.
  314.  *
  315.  * Results:
  316.  *    None.
  317.  *
  318.  * Side effects:
  319.  *    Some scsi commands are sent to the device.
  320.  *
  321.  *----------------------------------------------------------------------
  322.  */
  323.  
  324. ReturnStatus
  325. DevExabyteStatus(tapePtr, statusPtr, readPositionPtr)
  326.     ScsiTape         *tapePtr;    /* SCSI Tape */
  327.     Dev_TapeStatus    *statusPtr;    /* Status to fill in. */
  328.     Boolean        *readPositionPtr; /* OUT: should read position cmd
  329.                        * done? */
  330. {
  331.     ReturnStatus    status = SUCCESS;
  332.     int            size;
  333.     union {
  334.     Exb8200Sense    sense8200;
  335.     Exb8500Sense    sense8500;
  336.     } sense;
  337.  
  338.     size = sizeof(sense);
  339.     bzero((char *) &sense, size);
  340.     status = DevScsiRequestSense(tapePtr->devPtr, 0, 0, &size, 
  341.         (char *) &sense);
  342.     if (status != SUCCESS) {
  343.     goto done;
  344.     }
  345.     if (tapePtr->type == DEV_TAPE_EXB8200) {
  346.     Exb8200Sense    *sensePtr;
  347.     int        bufSize;
  348.     ParamListHeader    header;
  349.     BlockDesc    desc;
  350.     char        buffer[16];
  351.     if (size != sizeof(Exb8200Sense)) {
  352.         status = FAILURE;
  353.         goto done;
  354.     }
  355.     sensePtr = &sense.sense8200;
  356.     statusPtr->remaining = 
  357.         ((unsigned int) sensePtr->highRemainingTape << 16) |
  358.         ((unsigned int) sensePtr->midRemainingTape << 8) |
  359.         (sensePtr->lowRemainingTape);
  360.     statusPtr->dataError = 
  361.         ((unsigned int) sensePtr->highErrorCnt << 16) |
  362.         ((unsigned int) sensePtr->midErrorCnt << 8) |
  363.         (sensePtr->lowErrorCnt);
  364.     bufSize = sizeof(buffer);
  365.     status = DevScsiModeSense(tapePtr->devPtr, 0, 0, 0, 0, &bufSize, 
  366.             buffer);
  367.     if (status != SUCCESS) {
  368.         goto done;
  369.     }
  370.     bcopy((char *) buffer, (char *) &header, sizeof(header));
  371.     bcopy((char *) buffer + sizeof(header), (char *) &desc, sizeof(desc));
  372.     statusPtr->writeProtect = (header.writeProtect) ? TRUE : FALSE;
  373.     statusPtr->bufferedMode = header.bufferedMode;
  374.     statusPtr->serial[0] = '\0';
  375.     *readPositionPtr = FALSE;
  376.     } else if (tapePtr->type == DEV_TAPE_EXB8500) {
  377.     Exb8500Sense    *sensePtr;
  378.     int        bufSize;
  379.     ParamListHeader    header;
  380.     BlockDesc    desc;
  381.     Exb8500Inquiry    *inqPtr;
  382.     char        buffer[sizeof(ParamListHeader) + sizeof(BlockDesc)];
  383.     if (size != sizeof(Exb8500Sense)) {
  384.         status = FAILURE;
  385.         goto done;
  386.     }
  387.     sensePtr = &sense.sense8500;
  388.     statusPtr->remaining = 
  389.         ((unsigned int) sensePtr->highRemainingTape << 16) |
  390.         ((unsigned int) sensePtr->midRemainingTape << 8) |
  391.         (sensePtr->lowRemainingTape);
  392.     statusPtr->dataError = 
  393.         ((unsigned int) sensePtr->highErrorCnt << 16) |
  394.         ((unsigned int) sensePtr->midErrorCnt << 8) |
  395.         (sensePtr->lowErrorCnt);
  396.     statusPtr->readWriteRetry = sensePtr->readWriteRetry;
  397.     statusPtr->trackingRetry = sensePtr->trackingRetry;
  398.     bufSize = sizeof(buffer);
  399.     status = DevScsiModeSense(tapePtr->devPtr, 0, 0, 0, 0, &bufSize, 
  400.             buffer);
  401.     if (status != SUCCESS) {
  402.         goto done;
  403.     }
  404.     bcopy((char *) buffer, (char *) &header, sizeof(header));
  405.     bcopy((char *) buffer + sizeof(header), (char *) &desc, sizeof(desc));
  406.     statusPtr->writeProtect = (header.writeProtect) ? TRUE : FALSE;
  407.     statusPtr->bufferedMode = header.bufferedMode;
  408.     statusPtr->speed = header.speed;
  409.     statusPtr->density = desc.density;
  410.     inqPtr = (Exb8500Inquiry *) tapePtr->devPtr->inquiryDataPtr;
  411.     bcopy(inqPtr->serial, statusPtr->serial, sizeof(statusPtr->serial));
  412.     statusPtr->serial[10] = '\0';
  413.     *readPositionPtr = TRUE;
  414.     }
  415. done:
  416.     return status;
  417. }
  418.